﻿

namespace Tentacle.Downloader
{
    using System;
    using System.Collections.Generic;
    using System.Net;
    using Tentacle.Core;

    using WebRequest = Tentacle.Core.WebRequest;
    using static Tentacle.Utils.Hepler;

    public sealed class RemoteNode : IDownloader,IEqualityComparer<RemoteNode>
    {
        IClientService _service;
        int         _elapseTime;
        DateTime    _lastTime;
        WebSite     _site;
        bool        _sendPendding;

        public RemoteNode(IPEndPoint iP)
        {
            _service = new ClientService();
            _service.Connect(iP);
            _service.DownloadedCompleted += OnDownloadedCompleted;
            _service.DownloadedErrorRaised += OnDownloadedErrorRaised;
            _service.Disconnected += () => Disconnected?.Invoke(this);
        }

        #region IClientService Event And Property

        private void OnDownloadedErrorRaised(string obj)
        {
            DateTime last  = DateTime.Now;
            _elapseTime = (int)(last - _lastTime).TotalMilliseconds;
            _lastTime = last;
            _sendPendding = false;
            DownloadFailed?.Invoke(obj);
            
        }

        private void OnDownloadedCompleted(string obj)
        {
            DateTime last  = DateTime.Now;
            _elapseTime = (int)(last - _lastTime).TotalMilliseconds;
            _lastTime = last;
            _sendPendding = false;
            DownloadCompleted?.Invoke(new WebPage(obj,_site));
        }

        /// <summary>
        /// 
        /// </summary>
        public IPEndPoint LocalEndPoint {
            get {
                return _service.LocalEndPoint;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public string Guid {
            get {
                return _service.Guid;
            }
        }
        #endregion

        #region IDownloader

        /// <summary>
        /// 
        /// </summary>
        public int ElapseTime {
            get {
                return _elapseTime;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public DateTime LastTime {
            get {
                return _lastTime;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public bool CanDownload {
            get {
                return !_sendPendding;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public int WaitTime { get; set; }

        public bool SetTask(WebRequest request)
        {
            if (!_service.Connected) {
                return false;
            }
            else {
                _sendPendding = true;
                DateTime first = DateTime.Now;
                _lastTime = first;
                if (request.Token != null) {
                    _service.SetToken(request.Token.ToString());
                }

                _site = new WebSite(request.Site);
                _service.SetSite(request.Site);
                return true;
            }
        }

        

        public event DownloadCompletedHandler DownloadCompleted;

        #endregion        

        #region Override

        public override bool Equals(object obj)
        {
            if(obj is RemoteNode node) {
                return node._service.Guid == this._service.Guid;
            }
            return false;
        }

        public override string ToString()
        {
            return $"<{Guid},{LocalEndPoint}>";
        }

        public override int GetHashCode()
        {
            return _service.GetHashCode() ^ _service.Guid.GetHashCode();
        }

        public bool Equals(RemoteNode x, RemoteNode y)
        {
            return x._service.Guid == y._service.Guid;
        }

        public int GetHashCode(RemoteNode obj)
        {
            return obj._service.Guid.GetHashCode() ^ obj._service.GetHashCode();
        }
        #endregion

        public event DownloadFailedHandler DownloadFailed;
        public event Action<RemoteNode> Disconnected;
    }
}
